home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / arith2.com / ARITH_EN.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-02-27  |  6.4 KB  |  219 lines

  1. UNIT arith_en;
  2.  
  3.         { ------------------------------------------------------------------
  4.  
  5.           This program and its associates implement in Turbo Pascal v5
  6.           the aritmetic encoding/decoding algorithms presented in the papers
  7.  
  8.           "Arithmetic Coding for Data Compression"
  9.  
  10.                    by Ian     H. Witten
  11.                       Radford M. Neal
  12.                       John    G. Cleary
  13.  
  14.           pp 520 - 540 of June 1987 Communications of the ACM
  15.  
  16.           and
  17.  
  18.           "An Adaptive Dependency Source Model For Data Compression"
  19.  
  20.                    by David M. Abrahamson
  21.  
  22.           pp 77 - 83 of January 1989 Communications of the ACM
  23.  
  24.           ------------------------------------------------------------------
  25.  
  26.           Implemented by Ken Westerback : CompuServe 73547,3520
  27.  
  28.           version 1.0 released 89/02/19
  29.           version 2.0 released 89/02/27
  30.  
  31.           These programs, units and associated documentation are released
  32.           into the public domain to be used and abused as your whims
  33.           dictate.
  34.  
  35.           Feel free to distribute/incorporate/improve as desired.
  36.  
  37.           >>>>> Use at your own risk! <<<<<
  38.  
  39.           Comments and suggestions welcome via CompuServe.
  40.  
  41.           ------------------------------------------------------------------
  42.         }
  43.  
  44. INTERFACE uses dos;
  45.  
  46.  
  47. procedure start_encoding ( f_name : pathstr; model : char );
  48.  
  49. procedure encode_symbol  ( symbol : integer );
  50.  
  51. function  done_encoding  : longint; { return # characters written }
  52.  
  53.  
  54. IMPLEMENTATION uses arith_h, model_h;
  55.  
  56.  
  57. procedure start_encoding ( f_name : pathstr; model : char );
  58.           begin
  59.  
  60.           {I-}
  61.           assign ( bits_file, f_name );
  62.           rewrite ( bits_file, 1 );
  63.           {I+}
  64.  
  65.           if ioresult <> 0 then
  66.              begin
  67.              writeln;
  68.              writeln ( 'arith_en : error opening "', f_name, '"' );
  69.              writeln;
  70.              halt;
  71.              end;
  72.  
  73.           if model in valid_models then
  74.              blockwrite ( bits_file, model, 1 )
  75.           else
  76.              begin
  77.              writeln;
  78.              writeln ( 'arith_de : "', model, '" is not a valid model id' );
  79.              writeln;
  80.              halt;
  81.              end;
  82.  
  83.           bits_to_go := bits_per_buffer; { totally empty buffer assumed }
  84.  
  85.           end;
  86.  
  87. procedure bit_plus_follow ( bit : boolean );
  88.  
  89.           var bits_to_shift : byte;
  90.  
  91.           begin
  92.  
  93.           buffer := buffer shr 1;
  94.  
  95.           if ( bit ) then buffer := buffer or high_bit;
  96.  
  97.           inc ( bits_sent  );
  98.           dec ( bits_to_go );
  99.  
  100.           repeat
  101.  
  102.              if ( bits_to_go = 0 ) then
  103.                 begin
  104.                 big_buffer[ buffer_index ] := buffer;
  105.                 bits_to_go := bits_per_buffer;
  106.                 buffer := 0;
  107.                 inc ( buffer_index );
  108.                 if ( buffer_index = 512 ) then
  109.                    begin
  110.                    blockwrite ( bits_file, big_buffer, sizeof(big_buffer) );
  111.                    fillchar(big_buffer, sizeof(big_buffer), 0);
  112.                    buffer_index := 0;
  113.                    end;
  114.                 end;
  115.  
  116.              if ( bits_to_follow > 0 ) then { must shift some bits }
  117.                 begin
  118.                 if ( bits_to_follow <= bits_to_go ) then
  119.                    bits_to_shift := bits_to_follow
  120.                 else
  121.                    bits_to_shift := bits_to_go;
  122.                 inc ( bits_sent,      bits_to_shift );
  123.                 dec ( bits_to_go,     bits_to_shift );
  124.                 dec ( bits_to_follow, bits_to_shift );
  125.                 buffer := buffer shr bits_to_shift;
  126.                 if ( bit ) then
  127.                    { follow bits are zero - already done! }
  128.                 else
  129.                    buffer := buffer or one_masks[ bits_to_shift ];
  130.                 end;
  131.  
  132.              until (bits_to_follow = 0) and (bits_to_go <> 0);
  133.  
  134.           end; { bit_plus_follow }
  135.  
  136.  
  137. procedure encode_symbol ( symbol : integer );
  138.  
  139.           var range : longint;
  140.  
  141.           begin
  142.  
  143.           range := longint ( high - low ) + 1;
  144.  
  145.           { narrow the code region to that allotted to this symbol }
  146.  
  147.           high := low + ( range * cum_freq[ symbol-1 ]) div cum_freq[ 0 ] - 1;
  148.           low  := low + ( range * cum_freq[ symbol   ]) div cum_freq[ 0 ];
  149.  
  150.           { output bits }
  151.  
  152.           while true do
  153.                 begin
  154.  
  155.                 if      ( high < half ) then
  156.                    { output 0 if in low half }
  157.                    bit_plus_follow ( false )
  158.  
  159.                 else if ( low >= half ) then
  160.                    { output 1 and subtract offset to top if in high half }
  161.                    begin
  162.                    bit_plus_follow ( true );
  163.                    dec ( low,  half );
  164.                    dec ( high, half );
  165.                    end
  166.  
  167.                 else if ( low >= first_qtr ) and ( high < third_qtr ) then
  168.                    { output an opposite bit later and subtract offset to }
  169.                    { middle if in middle half                            }
  170.                    begin
  171.                    inc ( bits_to_follow );
  172.                    dec ( low,  first_qtr );
  173.                    dec ( high, first_qtr );
  174.                    end
  175.  
  176.                 else exit; { all done, so return to caller }
  177.  
  178.                 { scale up code range }
  179.  
  180.                 low  := low shl 1;
  181.                 high := (high shl 1) + 1
  182.  
  183.                 end;
  184.  
  185.           end; { encode_symbol }
  186.  
  187. function done_encoding : longint;
  188.  
  189.          var last_chars : integer; { # of characters in last long int }
  190.  
  191.          begin
  192.  
  193.          encode_symbol ( eof_symbol );
  194.  
  195.          { output two bits that select the quarter that the current code }
  196.          { range contains                                                }
  197.  
  198.          inc ( bits_to_follow );
  199.  
  200.          if   ( low < first_qtr ) then bit_plus_follow ( false )
  201.          else                          bit_plus_follow ( true  );
  202.  
  203.          buffer := buffer shr bits_to_go;
  204.  
  205.          last_chars := 4 - ( bits_to_go div 8 );
  206.  
  207.          big_buffer[ buffer_index ] := buffer;
  208.  
  209.          blockwrite ( bits_file, big_buffer, (buffer_index)*4+last_chars );
  210.  
  211.          close ( bits_file );
  212.  
  213.          done_encoding := ( ( bits_sent + 7 ) div 8 ) + 1; { +1 for model }
  214.  
  215.          end; { done_encoding }
  216.  
  217.  
  218. END. { arithmetic encoding implementation }
  219.